home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / tcp_ip / tnos / tnos100s / md5.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-04  |  18.5 KB  |  548 lines

  1. /*
  2.  ***********************************************************************
  3.  ** md5.c -- the source code for MD5 routines                         **
  4.  ** RSA Data Security, Inc. MD5 Message-Digest Algorithm              **
  5.  ** Created: 2/17/90 RLR                                              **
  6.  ** Revised: 1/91 SRD,AJ,BSK,JT Reference C ver., 7/10 constant corr. **
  7.  **          1992.2.13 Jouko Holopainen, 80x86 version                **
  8.  ***********************************************************************
  9.  */
  10.  
  11. /*
  12.  ***********************************************************************
  13.  ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved.  **
  14.  **                                                                   **
  15.  ** License to copy and use this software is granted provided that    **
  16.  ** it is identified as the "RSA Data Security, Inc. MD5 Message-     **
  17.  ** Digest Algorithm" in all material mentioning or referencing this  **
  18.  ** software or this function.                                        **
  19.  **                                                                   **
  20.  ** License is also granted to make and use derivative works          **
  21.  ** provided that such works are identified as "derived from the RSA  **
  22.  ** Data Security, Inc. MD5 Message-Digest Algorithm" in all          **
  23.  ** material mentioning or referencing the derived work.              **
  24.  **                                                                   **
  25.  ** RSA Data Security, Inc. makes no representations concerning       **
  26.  ** either the merchantability of this software or the suitability    **
  27.  ** of this software for any particular purpose.  It is provided "as  **
  28.  ** is" without express or implied warranty of any kind.              **
  29.  **                                                                   **
  30.  ** These notices must be retained in any copies of any part of this  **
  31.  ** documentation and/or software.                                    **
  32.  ***********************************************************************
  33.  */
  34.  
  35. #include "md5.h"
  36.  
  37. /*
  38.  ***********************************************************************
  39.  **  Message-digest routines:                                         **
  40.  **  To form the message digest for a message M                       **
  41.  **    (1) Initialize a context buffer mdContext using MD5Init        **
  42.  **    (2) Call MD5Update on mdContext and M                          **
  43.  **    (3) Call MD5Final on mdContext                                 **
  44.  **  The message digest is now in mdContext->digest[0...15]           **
  45.  ***********************************************************************
  46.  */
  47.  
  48. /* extern declaration */
  49. static void Transform ();
  50.  
  51. static unsigned char PADDING[64] = {
  52.   0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  53.   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  54.   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  55.   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  56.   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  57.   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  58.   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  59.   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  60. };
  61.  
  62. #ifndef    CPU386    /* Alternate defs exist for 386 assembler version */
  63. /* F, G, H and I are basic MD5 functions */
  64. #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
  65. #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
  66. #define H(x, y, z) ((x) ^ (y) ^ (z))
  67. #define I(x, y, z) ((y) ^ ((x) | (~z)))
  68.  
  69. /* ROTATE_LEFT rotates x left n bits */
  70. #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
  71.  
  72. /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */
  73. /* Rotation is separate from addition to prevent recomputation */
  74. #define FF(a, b, c, d, x, s, ac) \
  75.   {(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
  76.    (a) = ROTATE_LEFT ((a), (s)); \
  77.    (a) += (b); \
  78.   }
  79. #define GG(a, b, c, d, x, s, ac) \
  80.   {(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
  81.    (a) = ROTATE_LEFT ((a), (s)); \
  82.    (a) += (b); \
  83.   }
  84. #define HH(a, b, c, d, x, s, ac) \
  85.   {(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
  86.    (a) = ROTATE_LEFT ((a), (s)); \
  87.    (a) += (b); \
  88.   }
  89. #define II(a, b, c, d, x, s, ac) \
  90.   {(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
  91.    (a) = ROTATE_LEFT ((a), (s)); \
  92.    (a) += (b); \
  93.   }
  94. #endif    /* CPU386 */
  95.  
  96. /* The routine MD5Init initializes the message-digest context
  97.    mdContext. All fields are set to zero.
  98.  */
  99. void MD5Init (mdContext)
  100. MD5_CTX *mdContext;
  101. {
  102.   mdContext->i[0] = mdContext->i[1] = (UINT4)0;
  103.  
  104.   /* Load magic initialization constants.
  105.    */
  106.   mdContext->buf[0] = (UINT4)0x67452301;
  107.   mdContext->buf[1] = (UINT4)0xefcdab89;
  108.   mdContext->buf[2] = (UINT4)0x98badcfe;
  109.   mdContext->buf[3] = (UINT4)0x10325476;
  110. }
  111.  
  112. /* The routine MD5Update updates the message-digest context to
  113.    account for the presence of each of the characters inBuf[0..inLen-1]
  114.    in the message whose digest is being computed.
  115.  */
  116. void MD5Update (mdContext, inBuf, inLen)
  117. MD5_CTX *mdContext;
  118. unsigned char *inBuf;
  119. unsigned int inLen;
  120. {
  121.   UINT4 in[16];
  122.   int mdi;
  123.   unsigned int i, ii;
  124.  
  125.   /* compute number of bytes mod 64 */
  126.   mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
  127.  
  128.   /* update number of bits */
  129.   if ((mdContext->i[0] + ((UINT4)inLen << 3)) < mdContext->i[0])
  130.     mdContext->i[1]++;
  131.   mdContext->i[0] += ((UINT4)inLen << 3);
  132.   mdContext->i[1] += ((UINT4)inLen >> 29);
  133.  
  134. #ifdef    LITTLE_ENDIAN
  135.   /* Speedup for little-endian machines suggested in MD5 report --P Karn */
  136.     if(mdi == 0 && ((int)inBuf & 3) == 0){
  137.         while(inLen >= 64){
  138.             Transform(mdContext->buf,(UINT4 *)inBuf);
  139.             inLen -= 64;
  140.             inBuf += 64;
  141.         }        
  142.     }
  143. #endif    /* LITTLE_ENDIAN */
  144.   while (inLen--) {
  145.     /* add new character to buffer, increment mdi */
  146.     mdContext->in[mdi++] = *inBuf++;
  147.  
  148.     /* transform if necessary */
  149.     if (mdi == 0x40) {
  150.       for (i = 0, ii = 0; i < 16; i++, ii += 4)
  151.         in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |
  152.                 (((UINT4)mdContext->in[ii+2]) << 16) |
  153.                 (((UINT4)mdContext->in[ii+1]) << 8) |
  154.                 ((UINT4)mdContext->in[ii]);
  155.       Transform (mdContext->buf, in);
  156.       mdi = 0;
  157.     }
  158.   }
  159. }
  160.  
  161. /* The routine MD5Final terminates the message-digest computation and
  162.    ends with the desired message digest in mdContext->digest[0...15].
  163.  */
  164. void MD5Final (mdContext)
  165. MD5_CTX *mdContext;
  166. {
  167.   UINT4 in[16];
  168.   int mdi;
  169.   unsigned int i, ii;
  170.   unsigned int padLen;
  171.  
  172.   /* save number of bits */
  173.   in[14] = mdContext->i[0];
  174.   in[15] = mdContext->i[1];
  175.  
  176.   /* compute number of bytes mod 64 */
  177.   mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
  178.  
  179.   /* pad out to 56 mod 64 */
  180.   padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi);
  181.   MD5Update (mdContext, PADDING, padLen);
  182.  
  183.   /* append length in bits and transform */
  184.   for (i = 0, ii = 0; i < 14; i++, ii += 4)
  185.     in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |
  186.             (((UINT4)mdContext->in[ii+2]) << 16) |
  187.             (((UINT4)mdContext->in[ii+1]) << 8) |
  188.             ((UINT4)mdContext->in[ii]);
  189.   Transform (mdContext->buf, in);
  190.  
  191.   /* store buffer in digest */
  192.   for (i = 0, ii = 0; i < 4; i++, ii += 4) {
  193.     mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF);
  194.     mdContext->digest[ii+1] =
  195.       (unsigned char)((mdContext->buf[i] >> 8) & 0xFF);
  196.     mdContext->digest[ii+2] =
  197.       (unsigned char)((mdContext->buf[i] >> 16) & 0xFF);
  198.     mdContext->digest[ii+3] =
  199.       (unsigned char)((mdContext->buf[i] >> 24) & 0xFF);
  200.   }
  201. }
  202.  
  203. #ifndef    CPU386    /* Fast assembler version exists for 386/486 */
  204.  
  205. /* Basic MD5 step. Transforms buf based on in.
  206.  */
  207. static void Transform (buf, in)
  208. UINT4 *buf;
  209. UINT4 *in;
  210. {
  211.   UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
  212.  
  213.   /* Round 1 */
  214. #define S11 7
  215. #define S12 12
  216. #define S13 17
  217. #define S14 22
  218.   FF ( a, b, c, d, in[ 0], S11, 3614090360); /* 1 */
  219.   FF ( d, a, b, c, in[ 1], S12, 3905402710); /* 2 */
  220.   FF ( c, d, a, b, in[ 2], S13,  606105819); /* 3 */
  221.   FF ( b, c, d, a, in[ 3], S14, 3250441966); /* 4 */
  222.   FF ( a, b, c, d, in[ 4], S11, 4118548399); /* 5 */
  223.   FF ( d, a, b, c, in[ 5], S12, 1200080426); /* 6 */
  224.   FF ( c, d, a, b, in[ 6], S13, 2821735955); /* 7 */
  225.   FF ( b, c, d, a, in[ 7], S14, 4249261313); /* 8 */
  226.   FF ( a, b, c, d, in[ 8], S11, 1770035416); /* 9 */
  227.   FF ( d, a, b, c, in[ 9], S12, 2336552879); /* 10 */
  228.   FF ( c, d, a, b, in[10], S13, 4294925233); /* 11 */
  229.   FF ( b, c, d, a, in[11], S14, 2304563134); /* 12 */
  230.   FF ( a, b, c, d, in[12], S11, 1804603682); /* 13 */
  231.   FF ( d, a, b, c, in[13], S12, 4254626195); /* 14 */
  232.   FF ( c, d, a, b, in[14], S13, 2792965006); /* 15 */
  233.   FF ( b, c, d, a, in[15], S14, 1236535329); /* 16 */
  234.  
  235.   /* Round 2 */
  236. #define S21 5
  237. #define S22 9
  238. #define S23 14
  239. #define S24 20
  240.   GG ( a, b, c, d, in[ 1], S21, 4129170786); /* 17 */
  241.   GG ( d, a, b, c, in[ 6], S22, 3225465664); /* 18 */
  242.   GG ( c, d, a, b, in[11], S23,  643717713); /* 19 */
  243.   GG ( b, c, d, a, in[ 0], S24, 3921069994); /* 20 */
  244.   GG ( a, b, c, d, in[ 5], S21, 3593408605); /* 21 */
  245.   GG ( d, a, b, c, in[10], S22,   38016083); /* 22 */
  246.   GG ( c, d, a, b, in[15], S23, 3634488961); /* 23 */
  247.   GG ( b, c, d, a, in[ 4], S24, 3889429448); /* 24 */
  248.   GG ( a, b, c, d, in[ 9], S21,  568446438); /* 25 */
  249.   GG ( d, a, b, c, in[14], S22, 3275163606); /* 26 */
  250.   GG ( c, d, a, b, in[ 3], S23, 4107603335); /* 27 */
  251.   GG ( b, c, d, a, in[ 8], S24, 1163531501); /* 28 */
  252.   GG ( a, b, c, d, in[13], S21, 2850285829); /* 29 */
  253.   GG ( d, a, b, c, in[ 2], S22, 4243563512); /* 30 */
  254.   GG ( c, d, a, b, in[ 7], S23, 1735328473); /* 31 */
  255.   GG ( b, c, d, a, in[12], S24, 2368359562); /* 32 */
  256.  
  257.   /* Round 3 */
  258. #define S31 4
  259. #define S32 11
  260. #define S33 16
  261. #define S34 23
  262.   HH ( a, b, c, d, in[ 5], S31, 4294588738); /* 33 */
  263.   HH ( d, a, b, c, in[ 8], S32, 2272392833); /* 34 */
  264.   HH ( c, d, a, b, in[11], S33, 1839030562); /* 35 */
  265.   HH ( b, c, d, a, in[14], S34, 4259657740); /* 36 */
  266.   HH ( a, b, c, d, in[ 1], S31, 2763975236); /* 37 */
  267.   HH ( d, a, b, c, in[ 4], S32, 1272893353); /* 38 */
  268.   HH ( c, d, a, b, in[ 7], S33, 4139469664); /* 39 */
  269.   HH ( b, c, d, a, in[10], S34, 3200236656); /* 40 */
  270.   HH ( a, b, c, d, in[13], S31,  681279174); /* 41 */
  271.   HH ( d, a, b, c, in[ 0], S32, 3936430074); /* 42 */
  272.   HH ( c, d, a, b, in[ 3], S33, 3572445317); /* 43 */
  273.   HH ( b, c, d, a, in[ 6], S34,   76029189); /* 44 */
  274.   HH ( a, b, c, d, in[ 9], S31, 3654602809); /* 45 */
  275.   HH ( d, a, b, c, in[12], S32, 3873151461); /* 46 */
  276.   HH ( c, d, a, b, in[15], S33,  530742520); /* 47 */
  277.   HH ( b, c, d, a, in[ 2], S34, 3299628645); /* 48 */
  278.  
  279.   /* Round 4 */
  280. #define S41 6
  281. #define S42 10
  282. #define S43 15
  283. #define S44 21
  284.   II ( a, b, c, d, in[ 0], S41, 4096336452); /* 49 */
  285.   II ( d, a, b, c, in[ 7], S42, 1126891415); /* 50 */
  286.   II ( c, d, a, b, in[14], S43, 2878612391); /* 51 */
  287.   II ( b, c, d, a, in[ 5], S44, 4237533241); /* 52 */
  288.   II ( a, b, c, d, in[12], S41, 1700485571); /* 53 */
  289.   II ( d, a, b, c, in[ 3], S42, 2399980690); /* 54 */
  290.   II ( c, d, a, b, in[10], S43, 4293915773); /* 55 */
  291.   II ( b, c, d, a, in[ 1], S44, 2240044497); /* 56 */
  292.   II ( a, b, c, d, in[ 8], S41, 1873313359); /* 57 */
  293.   II ( d, a, b, c, in[15], S42, 4264355552); /* 58 */
  294.   II ( c, d, a, b, in[ 6], S43, 2734768916); /* 59 */
  295.   II ( b, c, d, a, in[13], S44, 1309151649); /* 60 */
  296.   II ( a, b, c, d, in[ 4], S41, 4149444226); /* 61 */
  297.   II ( d, a, b, c, in[11], S42, 3174756917); /* 62 */
  298.   II ( c, d, a, b, in[ 2], S43,  718787259); /* 63 */
  299.   II ( b, c, d, a, in[ 9], S44, 3951481745); /* 64 */
  300.  
  301.   buf[0] += a;
  302.   buf[1] += b;
  303.   buf[2] += c;
  304.   buf[3] += d;
  305. }
  306. #else    /* CPU386 */
  307. /* Fast 386 Borland C inline assembler version of the transform() function
  308.  * from the RSA Data Security, Inc, MD5 Message Digest Algorithm.
  309.  *
  310.  * This version uses native 32 bit registers, so it needs a 386 or 486 CPU.
  311.  *
  312.  * Because this function does *lots* of 32-bit operations, this version is
  313.  * MUCH faster than the reference C version compiled with a garden-
  314.  * variety 16-bit MS-DOS C compiler.
  315.  *
  316.  * Written and placed into the public domain on
  317.  * 22 February 1992 by Phil Karn, KA9Q
  318.  */
  319. #pragma inline
  320. /* I really shouldn't have to do this explicitly... */
  321. #ifdef    __COMPACT__
  322.     asm    .MODEL COMPACT
  323. #elif    __HUGE__
  324.     asm    .MODEL HUGE
  325. #elif    __LARGE__
  326.     asm    .MODEL LARGE
  327. #elif    __MEDIUM__
  328.     asm    .MODEL MEDIUM
  329. #elif    __SMALL__
  330.     asm    .MODEL SMALL
  331. #elif    __TINY__
  332.     asm    .MODEL TINY
  333. #endif
  334.  
  335. /* Code sequence common to all four rounds.
  336.  * evaluates a = b + (a + edi + x + t) <<< s)
  337.  */
  338. #define    COM(a,b,x,s,t)\
  339.     asm    add a,edi;\
  340.     asm    add a,x;\
  341.     asm    add a,t;\
  342.     asm    rol a,s;\
  343.     asm    add a,b;
  344.  
  345. /* Round 1 functions */
  346. /* edi = F(x,y,z) = (x & y) | (~x & z) */
  347. #define    F(x,y,z)\
  348.     asm    mov edi,x;\
  349.     asm    and edi,y;\
  350.     asm    mov esi,x;\
  351.     asm    not esi;\
  352.     asm    and esi,z;\
  353.     asm    or edi,esi
  354.  
  355. /* a = b + ((a + F(x,y,z) + x + t) <<< s); */
  356. #define    FF(a,b,c,d,x,s,t)\
  357.     F(b,c,d);\
  358.     COM(a,b,x,s,t)
  359.  
  360. /* Round 2 functions */
  361. /* edi = G(x,y,z) = F(z,x,y) = (x & z) | (y & ~z) */
  362. #define    G(x,y,z) F(z,x,y)
  363.  
  364. /* a = b + ((a + G(b,c,d) + x + t) <<< s) */
  365. #define    GG(a,b,c,d,x,s,t)\
  366.     G(b,c,d);\
  367.     COM(a,b,x,s,t)
  368.  
  369. /* Round 3 functions */
  370. /* edi = H(x,y,z) = x ^ y ^ z */
  371. #define    H(x,y,z)\
  372.     asm    mov edi,x;\
  373.     asm    xor edi,y;\
  374.     asm    xor edi,z
  375.  
  376. /* a = b + ((a + H(b,c,d) + x + t) <<< s) */
  377. #define    HH(a,b,c,d,x,s,t)\
  378.     H(b,c,d);\
  379.     COM(a,b,x,s,t)
  380.  
  381. /* Round 4 functions */
  382. /* edi = I(x,y,z) = y ^ (x | ~Z) */
  383. #define    I(x,y,z)\
  384.     asm    mov edi,z;\
  385.     asm    not edi;\
  386.     asm    or edi,x;\
  387.     asm    xor edi,y
  388.  
  389. /* a = b + ((a + I(b,c,d) + x + t) <<< s) */
  390. #define    II(a,b,c,d,x,s,t)\
  391.     I(b,c,d);\
  392.     COM(a,b,x,s,t)
  393.  
  394. #define    A    eax
  395. #define    B    ebx
  396. #define    C    ecx
  397. #define    D    edx
  398.  
  399. static void
  400. Transform(buf,input)
  401. long *buf;
  402. long *input;
  403. {
  404.     asm    .386;    /* Allow use of 32-bit general registers */
  405.  
  406.     /* Save caller's registers */
  407.     asm    push si;
  408.     asm    push di;
  409.     asm    push es;
  410.     asm    if @DataSize NE 0
  411.     asm        push ds;
  412.     asm    endif
  413.  
  414.     /* Get buf argument */
  415.     asm    if @DataSize NE 0
  416.     asm        lds si,buf;
  417.     asm    else
  418.     asm        mov si,buf;
  419.     asm    endif
  420.     asm    mov A,dword ptr si[0*4];    /* A = buf[0] */
  421.     asm    mov B,dword ptr si[1*4];    /* B = buf[1] */
  422.     asm    mov C,dword ptr si[2*4];    /* C = buf[2] */
  423.     asm    mov D,dword ptr si[3*4];    /* D = buf[3] */
  424.  
  425.     /* Warning: This makes our other args inaccessible until bp
  426.      * is restored!
  427.     */
  428.     asm    push bp;
  429.     asm    les bp,input
  430.  
  431. /* Round 1. The *4 factors in the subscripts to bp account for the
  432.  * byte offsets of each long element in the input array.
  433.  */
  434. #define S11 7
  435. #define S12 12
  436. #define S13 17
  437. #define S14 22
  438.     FF(A,B,C,D,es:bp[ 0*4],S11,3614090360); /* 1 */
  439.     FF(D,A,B,C,es:bp[ 1*4],S12,3905402710); /* 2 */
  440.     FF(C,D,A,B,es:bp[ 2*4],S13, 606105819); /* 3 */
  441.     FF(B,C,D,A,es:bp[ 3*4],S14,3250441966); /* 4 */
  442.     FF(A,B,C,D,es:bp[ 4*4],S11,4118548399); /* 5 */
  443.     FF(D,A,B,C,es:bp[ 5*4],S12,1200080426); /* 6 */
  444.     FF(C,D,A,B,es:bp[ 6*4],S13,2821735955); /* 7 */
  445.     FF(B,C,D,A,es:bp[ 7*4],S14,4249261313); /* 8 */
  446.     FF(A,B,C,D,es:bp[ 8*4],S11,1770035416); /* 9 */
  447.     FF(D,A,B,C,es:bp[ 9*4],S12,2336552879); /* 10 */
  448.     FF(C,D,A,B,es:bp[10*4],S13,4294925233); /* 11 */
  449.     FF(B,C,D,A,es:bp[11*4],S14,2304563134); /* 12 */
  450.     FF(A,B,C,D,es:bp[12*4],S11,1804603682); /* 13 */
  451.     FF(D,A,B,C,es:bp[13*4],S12,4254626195); /* 14 */
  452.     FF(C,D,A,B,es:bp[14*4],S13,2792965006); /* 15 */
  453.     FF(B,C,D,A,es:bp[15*4],S14,1236535329); /* 16 */
  454.  
  455. /* Round 2 */
  456. #define S21 5
  457. #define S22 9
  458. #define S23 14
  459. #define S24 20
  460.     GG(A,B,C,D,es:bp[ 1*4],S21,4129170786); /* 17 */
  461.     GG(D,A,B,C,es:bp[ 6*4],S22,3225465664); /* 18 */
  462.     GG(C,D,A,B,es:bp[11*4],S23, 643717713); /* 19 */
  463.     GG(B,C,D,A,es:bp[ 0*4],S24,3921069994); /* 20 */
  464.     GG(A,B,C,D,es:bp[ 5*4],S21,3593408605); /* 21 */
  465.     GG(D,A,B,C,es:bp[10*4],S22,  38016083); /* 22 */
  466.     GG(C,D,A,B,es:bp[15*4],S23,3634488961); /* 23 */
  467.     GG(B,C,D,A,es:bp[ 4*4],S24,3889429448); /* 24 */
  468.     GG(A,B,C,D,es:bp[ 9*4],S21, 568446438); /* 25 */
  469.     GG(D,A,B,C,es:bp[14*4],S22,3275163606); /* 26 */
  470.     GG(C,D,A,B,es:bp[ 3*4],S23,4107603335); /* 27 */
  471.     GG(B,C,D,A,es:bp[ 8*4],S24,1163531501); /* 28 */
  472.     GG(A,B,C,D,es:bp[13*4],S21,2850285829); /* 29 */
  473.     GG(D,A,B,C,es:bp[ 2*4],S22,4243563512); /* 30 */
  474.     GG(C,D,A,B,es:bp[ 7*4],S23,1735328473); /* 31 */
  475.     GG(B,C,D,A,es:bp[12*4],S24,2368359562); /* 32 */
  476.  
  477. /* Round 3 */
  478. #define S31 4
  479. #define S32 11
  480. #define S33 16
  481. #define S34 23
  482.     HH(A,B,C,D,es:bp[ 5*4],S31,4294588738); /* 33 */
  483.     HH(D,A,B,C,es:bp[ 8*4],S32,2272392833); /* 34 */
  484.     HH(C,D,A,B,es:bp[11*4],S33,1839030562); /* 35 */
  485.     HH(B,C,D,A,es:bp[14*4],S34,4259657740); /* 36 */
  486.     HH(A,B,C,D,es:bp[ 1*4],S31,2763975236); /* 37 */
  487.     HH(D,A,B,C,es:bp[ 4*4],S32,1272893353); /* 38 */
  488.     HH(C,D,A,B,es:bp[ 7*4],S33,4139469664); /* 39 */
  489.     HH(B,C,D,A,es:bp[10*4],S34,3200236656); /* 40 */
  490.     HH(A,B,C,D,es:bp[13*4],S31, 681279174); /* 41 */
  491.     HH(D,A,B,C,es:bp[ 0*4],S32,3936430074); /* 42 */
  492.     HH(C,D,A,B,es:bp[ 3*4],S33,3572445317); /* 43 */
  493.     HH(B,C,D,A,es:bp[ 6*4],S34,  76029189); /* 44 */
  494.     HH(A,B,C,D,es:bp[ 9*4],S31,3654602809); /* 45 */
  495.     HH(D,A,B,C,es:bp[12*4],S32,3873151461); /* 46 */
  496.     HH(C,D,A,B,es:bp[15*4],S33, 530742520); /* 47 */
  497.     HH(B,C,D,A,es:bp[ 2*4],S34,3299628645); /* 48 */
  498.  
  499. /* Round 4 */
  500. #define S41 6
  501. #define S42 10
  502. #define S43 15
  503. #define S44 21
  504.     II(A,B,C,D,es:bp[ 0*4],S41,4096336452); /* 49 */
  505.     II(D,A,B,C,es:bp[ 7*4],S42,1126891415); /* 50 */
  506.     II(C,D,A,B,es:bp[14*4],S43,2878612391); /* 51 */
  507.     II(B,C,D,A,es:bp[ 5*4],S44,4237533241); /* 52 */
  508.     II(A,B,C,D,es:bp[12*4],S41,1700485571); /* 53 */
  509.     II(D,A,B,C,es:bp[ 3*4],S42,2399980690); /* 54 */
  510.     II(C,D,A,B,es:bp[10*4],S43,4293915773); /* 55 */
  511.     II(B,C,D,A,es:bp[ 1*4],S44,2240044497); /* 56 */
  512.     II(A,B,C,D,es:bp[ 8*4],S41,1873313359); /* 57 */
  513.     II(D,A,B,C,es:bp[15*4],S42,4264355552); /* 58 */
  514.     II(C,D,A,B,es:bp[ 6*4],S43,2734768916); /* 59 */
  515.     II(B,C,D,A,es:bp[13*4],S44,1309151649); /* 60 */
  516.     II(A,B,C,D,es:bp[ 4*4],S41,4149444226); /* 61 */
  517.     II(D,A,B,C,es:bp[11*4],S42,3174756917); /* 62 */
  518.     II(C,D,A,B,es:bp[ 2*4],S43, 718787259); /* 63 */
  519.     II(B,C,D,A,es:bp[ 9*4],S44,3951481745); /* 64 */
  520.  
  521.     asm pop bp;        /* We can address our args again */
  522.     asm    if @DataSize NE 0
  523.     asm        lds si,buf
  524.     asm    else
  525.     asm        mov si,buf;
  526.     asm    endif
  527.     asm add    dword ptr si[0*4],A;    /* buf[0] += A */
  528.     asm add dword ptr si[1*4],B;    /* buf[1] += B */
  529.     asm add dword ptr si[2*4],C;    /* buf[2] += C */
  530.     asm add dword ptr si[3*4],D;    /* buf[3] += D */
  531.  
  532.     /* Restore caller's registers */
  533.     asm    if @DataSize NE 0
  534.     asm        pop ds
  535.     asm    endif
  536.  
  537.     asm    pop es;
  538.     asm    pop di;
  539.     asm    pop si;
  540. }
  541. #endif    /* CPU386 */
  542.  
  543. /*
  544.  ***********************************************************************
  545.  ** End of md5.c                                                      **
  546.  ******************************** (cut) ********************************
  547.  */
  548.